package org.bbsoft.catchme.model;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * some ugly code to make transaction management nice and dumb.
 * 
 * This class is not thread safe and should only be used in request scope
 * 
 */
public class EntityManagerService {

	private EntityManagerFactory entitiyManagerFactory;

	private final Logger logger = LoggerFactory.getLogger(getClass());

	private EntityManager entityManager;

	/**
	 * open Transaction manager; if readonly no JPA transaction is actually
	 * started, meaning you will have no persistence store. You can still
	 * persist stuff, but the entities won't become managed.
	 */
	public EntityManagerService() {

	}

	/**
	 * creates a new entity manager if called at first time or
	 * {@link EntityManagerService#release()} was called before or returns the
	 * current one.
	 */
	public void init() {

		if (entityManager != null) {
			return;
		}
		entityManager = entitiyManagerFactory.createEntityManager();

		entityManager.getTransaction().begin();

	}

	/**
	 * Returns the current entity manager or null if no current entity manager
	 * is existing
	 */
	public EntityManager getEntityManager() {
		return entityManager;
	}

	/**
	 * Close the entity manager, properly committing or rolling back a
	 * transaction if one is still active.
	 */
	public void release() {

		if (entityManager == null) {
			return;
		}

		try {
			if (entityManager.getTransaction().isActive()) {

				if (entityManager.getTransaction().getRollbackOnly()) {
					entityManager.getTransaction().rollback();
				} else {
					entityManager.getTransaction().commit();
				}
			}

		} finally {
			entityManager.close();
			entityManager = null;

		}

	}

	/**
	 * Mark the transaction as rollback only, if there is an active transaction
	 * to begin with.
	 */
	public void setRollbackOnly() {

		if (entityManager != null) {
			entityManager.getTransaction().setRollbackOnly();
		}

	}

	public boolean isRollbackOnly() {

		return entityManager != null
				&& entityManager.getTransaction().getRollbackOnly();

	}

	public void setEntityManagerFactory(EntityManagerFactory emf) {
		this.entitiyManagerFactory = emf;
	}

}
